﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;

namespace OpenWaves.EPiServer.Localization.Model
{
    public class LangFileEntry
    {
        public const string BaseTypeAttributeName = "type";
        public const string InterfaceAttributeName = "interface";
        public const string OverrideAttributeName = "override";

        public LangFileEntry(string name, LangFileEntry parent)
        {
            this.Name = name;
            this.Parent = parent;
        }

        private string baseType;
        private string @interface;

        public readonly LangFileEntry Parent;
        public readonly string Name;
        public readonly List<LangFileEntry> Entries = new List<LangFileEntry>();
        public string BaseType
        {
            get
            {
                return this.baseType;
            }
            set
            {
                if (!string.IsNullOrEmpty(this.@interface))
                {
                    string message = string.Format("Cannot define both base type and interface for element '{0}' (syntax not supported by LangaugeManager)", this.GetRootPath());
                    throw new InvalidOperationException(message);
                }

                this.baseType = value;
            }
        }
        public string Interface
        {
            get
            {
                return this.@interface;
            }
            set
            {
                if (!string.IsNullOrEmpty(this.baseType))
                {
                    string message = string.Format("Cannot define both base type and interface for element '{0}' (syntax not supported by LangaugeManager)", this.GetRootPath());
                    throw new InvalidOperationException(message);
                }

                this.@interface = value;
            }
        }

        public string NameAttribute { get; set; }

        public virtual string GetRootPath()
        {
            string selector = this.GetPathSegment();
            if (this.Parent == null)
            {
                return "/" + selector;
            }

            return this.Parent.GetRootPath() + "/" + selector;
        }

        public virtual string GetFullClassName()
        {
            var className = this.GetClassName();
            if (this.Parent == null)
            {
                return className;
            }

            return this.Parent.GetClassName() + "." + className;
        }


        public string GetPathSegment()
        {
            if (this.BaseType != null)
            {
                return string.Format("{0}[@{1}='{2}']", this.Name, BaseTypeAttributeName, this.BaseType);
            }
            if (this.Interface != null)
            {
                return string.Format("{0}[@{1}='{2}']", this.Name, InterfaceAttributeName, this.Interface);
            }
            if (this.NameAttribute != null)
            {
                return string.Format("{0}[@name='{1}']", this.Name, this.NameAttribute);
            }
            return this.Name;
        }

        public void InitializeWithXElement(XElement element)
        {
            if (element.Attribute(InterfaceAttributeName) != null)
            {
                this.Interface = element.Attribute(InterfaceAttributeName).Value;
            }

            if (element.Attribute(BaseTypeAttributeName) != null && element.Attribute(BaseTypeAttributeName).Value.StartsWith("EPiServer.") == false)
            {
                this.BaseType = element.Attribute(BaseTypeAttributeName).Value;
            }

            if (element.Attribute("name") != null)
            {
                this.NameAttribute = element.Attribute("name").Value;
            }
        }

        public string GetClassName()
        {
            var className = NamingConvention.GenerateIdentifier(this.Name) + NamingConvention.GenerateIdentifier(this.NameAttribute) + "Keys";
            return this.Parent != null && this.Parent.GetClassName() == className ? "_" + className : className;
        }

        public string GetMemberName()
        {
            var result = NamingConvention.GenerateIdentifier(this.Name) + NamingConvention.GenerateIdentifier(this.NameAttribute);
            var memberName = result == "Name" ? "_Name" : result;
            return memberName;
        }

        public string GetFieldName()
        {
            var propertyName = this.GetPropertyName();
            var result = char.ToLower(propertyName[0]) + propertyName.Substring(1);
            return result == "_Name" ? "_name" : result;
        }

        public string GetPropertyName()
        {
            return this.GetMemberName();
        }
    }
}